package com.hlmedicals.app.conf.intercepter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import com.hlmedicals.app.system.entity.HisDoctor;
import com.hlmedicals.app.system.entity.HisThirdParty;
import com.lostad.app.common.exception.ApiException;
import com.lostad.app.common.service.CacheService;
import com.lostad.app.common.util.SpringUtil;
import com.lostad.app.common.util.Validator;
import com.lostad.app.common.util.net.IpUtil;
import com.lostad.app.common.util.net.RequestUtil;
import com.lostad.app.common.util.net.ResponseUtil;
import com.lostad.app.common.util.security.SignUtil;
import com.lostad.app.common.vo.JsonRe;

/**
 * 权限拦截器
 * 
 */
public class AuthInterceptor implements HandlerInterceptor {

	private static final Logger logger = Logger.getLogger(AuthInterceptor.class);
	private List<String> excludeUrls = new ArrayList<String>();

	private CacheService cacheService;

	public List<String> getExcludeUrls() {
		return excludeUrls;
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}

	/**
	 * 在controller后拦截
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object,Exception exception) throws Exception {
		try{
			response.setHeader("Cache-Control", "no-cache"); 
			if(!response.isCommitted()){
				response.getWriter().flush();
				response.getWriter().close();
			}
		
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object,ModelAndView modelAndView) throws Exception {
		response.setHeader("Cache-Control", "no-cache"); 
	}

	/**
	 * 在controller前拦截
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
		response.setHeader("Cache-Control", "no-cache"); 
		String requestPath = RequestUtil.getRequestPath(request);// 用户访问的资源地址
		if (excludeUrls.contains(requestPath) || requestPath.startsWith("rest/hisFileDownload")||requestPath.startsWith("EPController.do?EPShowCFView")) {
				return true;
		}
		try {
			if (requestPath.startsWith("rest/")) {// contentType 为json/application的请求，不进行登录拦截,需要通过token进行鉴权 ssz 20160315
				String signType = request.getHeader("signType");
				if(Validator.isEmpty(signType)){
					return isTokenOk(request);
				}else if("MD5".equalsIgnoreCase(signType)){////新的对外接口权限校验，不再走rest前缀的20170413方法,下面是为了兼容旧的项目/
					 verifyMd5(request, response, requestPath);
				}
			}else if (requestPath.startsWith("apiOpen/")) {//contentType 为json/application的请求，外部系统调用
				return verifyMd5(request, response, requestPath);
			}
		} catch (ApiException e) {
			ResponseUtil.flushJson(response, new JsonRe(-1, e.getMessage(), null));
		}
		return false;
	}

	/**
	 * 签名认证，支持json和form表单提交
	 * @param request
	 * @param response
	 * @param requestPath
	 * @return
	 * @throws IOException
	 */
	public boolean verifyMd5(HttpServletRequest request,HttpServletResponse response, String requestPath)throws Exception {
		String signType = request.getHeader("signType");
		String appId = request.getHeader("appId");
		String sign = request.getHeader("sign");//
		logger.info("signType:"+signType+" appId:"+appId+" sign:"+sign);
		if("MD5".equalsIgnoreCase(signType)){
			String contentType = request.getContentType();
			String signNew = null ;
			logger.debug(requestPath+"\n>>>>>>>>>>>>>> contentType:"+contentType);
			if(cacheService==null){
				cacheService = SpringUtil.getBean("cacheService");
			}
			HisThirdParty p = cacheService.getHisThirdParty(appId);
			
			if(contentType.contains("application/json")){//json
				String data4Sign = IOUtils.toString(request.getInputStream(),"utf-8");
				signNew = SignUtil.signMD5(data4Sign, p.getSecretKey());
			}else{//from
				String data4Sign = SignUtil.getParam4Sign(request);
				signNew = SignUtil.signMD5(data4Sign, p.getSecretKey());
			}
			
			if(!signNew.equals(sign)){
				throw new ApiException("签名认证失败!");
			}
		  }else{
			throw new ApiException("签名方式未设置!");
		  }
		
		return true;
	}


	/**
	 * 
	 * 方法的说明
	 * @param 
	 * @return boolean
	 */
	private boolean isTokenOk(HttpServletRequest request){
		String token = request.getHeader("token");
		try{
			if (Validator.isEmpty(token)) {
				throw new ApiException("token不能为空！");
			}

			String doctorId = request.getHeader("doctorId");
			if (Validator.isEmpty(doctorId)) {
				throw new ApiException("未在header中添加doctorId");
			}

			HisDoctor doct = cacheService.getHisDoctor(doctorId);
			if (!token.equals(doct.getToken())) {// 不一致
				logger.error("error! doct.getToken(): " + doct.getToken() + "  doctorId: " + doct.getId()+ "--------------token:" + token);
				throw new ApiException("token失效，请重新登录！");
			}
		}catch(Exception e){
			e.printStackTrace();
			logger.error("IP:"+IpUtil.getIpAddr(request)+"#################\n"+e.getMessage());
			throw e;
		}
//		
		return true;
	}
	
	/**
	 * 转发
	 * 
	 * @param user
	 * @param req
	 * @return
	 */
	@RequestMapping(params = "forword")
	public ModelAndView forword(HttpServletRequest request) {
		System.out.println("##########################forword(HttpServletRequest request)");
		return new ModelAndView(new RedirectView("loginController.do?login"));
	}

}
